use Test::More;
use Cwd;
use FindBin;
use lib Cwd::abs_path("$FindBin::Bin/../../../lib");
use lib Cwd::abs_path("$FindBin::Bin/../../../generate/MyProject/lib");
use lib Cwd::abs_path("$FindBin::Bin/tlib");
use strict;
use warnings;

use MyProject;
use MyTest;
my $proj = 'MyProject';
my($DBH, $DBN) = MyTest->setup($proj);
ok $DBN;

is my $se = $proj->schema->ExampleEntry,
    'MyProject::Schema::Default::ExampleEntry';
is my $sec = $proj->schema->ExampleEntryContent,
    'MyProject::Schema::Default::ExampleEntryContent';
is my $sem = $proj->schema->ExampleEntryMember,
    'MyProject::Schema::Default::ExampleEntryMember';
is my $sm = $proj->schema->ExampleMember,
    'MyProject::Schema::Default::ExampleMember';

$proj->begin;
eval{
    MyTest->migrate($proj);
    
    {
        my $e1  = $se->new;
        my $e2  = $se->new;
        my $em1 = $sem->new;
        my $em2 = $sem->new;
        
        $e1->entry_members([$em1, $em2]);
        is join('#', @{$e1->entry_members}), "$em1#$em2";
        is $em1->entry, $e1;
        is $em2->entry, $e1;
        
        $e1->entry_members([$em2]);
        is join('#', @{$e1->entry_members}), $em2;
        is $em1->entry, undef;
        is $em2->entry, $e1;
        
        $e2->entry_members([$em1, $em2]);
        is join('#', @{$e1->entry_members}), '';
        is join('#', @{$e2->entry_members}), "$em1#$em2";
        is $em1->entry, $e2;
        is $em2->entry, $e2;
        
        $em1->entry($e1);
        $em2->entry($e1);
        is join('#', @{$e1->entry_members}), "$em1#$em2";
        is join('#', @{$e2->entry_members}), '';
        is $em1->entry, $e1;
        is $em2->entry, $e1;
        
        $em1->entry(undef);
        is join('#', @{$e1->entry_members}), $em2;
        is join('#', @{$e2->entry_members}), '';
        is $em1->entry, undef;
        is $em2->entry, $e1;
        
        $em1->entry($e2);
        is join('#', @{$e1->entry_members}), $em2;
        is join('#', @{$e2->entry_members}), $em1;
        is $em1->entry, $e2;
        is $em2->entry, $e1;
        
        my $e3  = $se->new;
        my $em3 = $sem->new;
        $e3->entry_members([$em3]);
        is join('#', @{$e3->entry_members}), $em3;
        is $em3->entry, $e3;
        
        $e1->entry_members([$em3]);
        is join('#', @{$e1->entry_members}), $em3;
        is join('#', @{$e2->entry_members}), $em1;
        is join('#', @{$e3->entry_members}), '';
        is $em1->entry, $e2;
        is $em2->entry, undef;
        is $em3->entry, $e1;
        
        $e1->entry_members([$em1, $em2, $em3]);
        is join('#', @{$e1->entry_members}), "$em1#$em2#$em3";
        is join('#', @{$e2->entry_members}), '';
        is join('#', @{$e3->entry_members}), '';
        is $em1->entry, $e1;
        is $em2->entry, $e1;
        is $em3->entry, $e1;
        
        $e2->entry_members([$em2]);
        is join('#', @{$e1->entry_members}), "$em1#$em3";
        is join('#', @{$e2->entry_members}), $em2;
        is join('#', @{$e3->entry_members}), '';
        is $em1->entry, $e1;
        is $em2->entry, $e2;
        is $em3->entry, $e1;
    }
    
    my @r;
    {
        $proj->_weaken_($r[0] = my $e = $se->new);
        $proj->_weaken_($r[1] = my $ec = $sec->new);
        
        $e->content($ec);
        my $i = "$ec";
        is $e->content, $i;
        undef $ec;
        is $e->content, $i;
    }
    is_deeply \@r, [undef, undef];
    
    {
        $proj->_weaken_($r[0] = my $e = $se->new);
        $proj->_weaken_($r[1] = my $ec = $sec->new);
        
        $e->content($ec);
        my $i = "$e";
        is $ec->entry, $i;
        undef $e;
        is $ec->entry, $i;
    }
    is_deeply \@r, [undef, undef];
    
    {
        $proj->_weaken_($r[0] = my $e = $se->new);
        $proj->_weaken_($r[1] = my $ec = $sec->new);
        
        $ec->entry($e);
        my $i = "$e";
        is $ec->entry, $i;
        undef $e;
        is $ec->entry, $i;
    }
    is_deeply \@r, [undef, undef];
    
    {
        $proj->_weaken_($r[0] = my $e = $se->new);
        $proj->_weaken_($r[1] = my $ec = $sec->new);
        
        $ec->entry($e);
        my $i = "$ec";
        is $e->content, $i;
        undef $ec;
        is $e->content, $i;
    }
    is_deeply \@r, [undef, undef];
    
    
    
    $se->new->insert;
    $sec->new({entry_id => 1})->insert;
    foreach(1 .. 3){
        $sm->new->insert;
        $sem->new({entry_id => 1, member_id => $_})->insert;
    }
    {
        my $e1 = $se->find(1);
        is $e1->id, 1;
        is $e1->lock_version, 1;
        
        my $ec = $e1->content;
        is $ec->entry_id, 1;
        
        my $e2 = $ec->entry;
        is $e1, $e2;
        is $e2->content, $ec;
        
        my $em = $e1->entry_members;
        is join('#', sort map{ $_->member_id } @$em), '1#2#3';
        is $em->[0]->entry, $e1;
        is $em->[1]->entry, $e1;
        is $em->[2]->entry, $e1;
    }
    
    {
        my $em1 = $sem->find([1, 2]);
        my $e1 = $em1->entry;
        
        my $em = $e1->entry_members;
        is join('#', sort map{ $_->member_id } @$em), '1#2#3';
        is $em->[1], $em1;
    }
    
    foreach my $e (undef, $se->new){
        my $em1 = $sem->find([1, 2]);
        my $e1 = $em1->entry;
        
        $em1->entry($e);
        my $em = $e1->entry_members;
        
        is $em1->entry_id, undef if !$e;
        is join('#', sort map{ $_->member_id } @{$e1->entry_members}), '1#3';
    }
    
    foreach my $e (undef, $se->new){
        my $em1 = $sem->find([1, 2]);
        my $e1 = $em1->entry;
        
        my $em = $e1->entry_members;
        $em1->entry($e);
        
        is $em1->entry_id, undef if !$e;
        is join('#', sort map{ $_->member_id } @{$e1->entry_members}), '1#3';
    }
    
    {
        my $e1 = $se->find(1);
        my $em = $e1->entry_members;
        my $em1 = $em->[1];
        is $em1->entry_id, 1;
        $e1->entry_members([$em->[0], $em->[2]]);
        is $em1->entry_id, undef;
    }
};
$proj->end;

my $msg = $@;
$DBH->prepare("drop database $DBN;")->execute;
die $msg if $msg;
